﻿using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Windows.Forms;

namespace ItemTemplateInstaller
{
	public abstract class VSTemplateInstallerBase : InstallerBase
	{
		private const string FILE_NAME = "ObservablePropertyItemTemplate.zip";
		private const string SUB_FOLDER = @"ItemTemplates\CSharp\Code\1033\";

		protected abstract string ProductTitle { get; }
		protected abstract int VSVersionMajor { get; }
		protected abstract string ProductSetupCode { get; }

		protected void InstallInternal(IDictionary stateSaver)
		{
			var installDir = InstallDir;

			if (string.IsNullOrEmpty(installDir))
				return;

			using (var form = new Progress())
			{
				form.Show();
				form.Focus();

				form.Message = "Locating " + ProductTitle + " install location...";
				Application.DoEvents();

				if (Directory.Exists(installDir))
				{
					var msenv_dll = Path.Combine(installDir, "msenv.dll");

					var file = FileVersionInfo.GetVersionInfo(msenv_dll);

					if (file.ProductMajorPart == VSVersionMajor)
					{
						form.Message = ProductTitle + " found.";
						Application.DoEvents();

						CopyTemplates(installDir, form);

						RegisterTemplates(form);

						stateSaver.Add(ProductSetupCode, true);
					}
				}

				form.Close();
			}
		}

		protected void UninstallInternal(IDictionary stateSaver)
		{
			if (stateSaver == null)
				return;

			if (!stateSaver.Contains(ProductSetupCode))
				return;

			var installDir = InstallDir;

			if (string.IsNullOrEmpty(installDir))
				return;

			using (var form = new Progress())
			{
				form.Show();
				form.Focus();
				DeleteTemplates(installDir, form);
				UnregisterTemplates(form);

				form.Close();
			}
		}

		private void ResetTemplates()
		{
			var process = Process.Start(DevEnvLocation, "/installvstemplates");

			if (process != null)
				process.WaitForExit();
		}

		private void RegisterTemplates(Progress form)
		{
			form.Message = "Registering templates with " + ProductTitle + ".";
			Application.DoEvents();
			ResetTemplates();
			form.Message = "Registering templates with " + ProductTitle + " complete.";
			Application.DoEvents();
		}

		private void UnregisterTemplates(Progress form)
		{
			form.Message = "Unregistering templates from " + ProductTitle + ".";
			Application.DoEvents();
			ResetTemplates();
			form.Message = "Unregistering templates from " + ProductTitle + " complete.";
			Application.DoEvents();
		}

		private void CopyTemplates(string installDir, Progress form)
		{
			form.Message = "Copying templates to " + ProductTitle;
			Application.DoEvents();
			File.Copy(Path.Combine(TargetDir, FILE_NAME), Path.Combine(installDir, SUB_FOLDER, FILE_NAME), true);
		}

		private void DeleteTemplates(string installDir, Progress form)
		{
			form.Message = "Deleting templates from " + ProductTitle;
			Application.DoEvents();
			File.Delete(Path.Combine(installDir, SUB_FOLDER, FILE_NAME));
		}

		private string TargetDir
		{
			get
			{
				var location = Assembly.GetExecutingAssembly().Location;
				return Path.GetDirectoryName(location);
			}
		}
	}
}